{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Self Discover Pack\n",
    "\n",
    "<a href=\"https://colab.research.google.com/github/run-llama/llama_index/blob/main/llama-index-packs/llama-index-packs-self-discover/examples/self_discover.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>\n",
    "\n",
    "This LlamaPack implements [Self-Discover: Large Language Models Self-Compose Reasoning Structures](https://arxiv.org/abs/2402.03620) paper.\n",
    "\n",
    "It has two stages for the given task:\n",
    "\n",
    "1. STAGE-1:\n",
    "\n",
    "    a. SELECT: Selects subset of reasoning Modules.\n",
    "\n",
    "    b. ADAPT: Adapts selected reasoning modules to the task.\n",
    "\n",
    "    c. IMPLEMENT: It gives reasoning structure for the task.\n",
    "    \n",
    "2. STAGE-2: Uses the generated reasoning structure for the task to generate an answer.\n",
    "\n",
    "\n",
    "The implementation is inspired from the [codebase](https://github.com/catid/self-discover)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import nest_asyncio\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"<Your OpenAI API Key>\"\n",
    "from llama_index.llms.openai import OpenAI\n",
    "\n",
    "llm = OpenAI(\"gpt-4\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load / Download Pack\n",
    "\n",
    "There are two ways to use the LlamaPack.\n",
    "\n",
    "1. Do `download_llama_pack` to load the Self-Discover LlamaPack.\n",
    "2. Directly use `SelfDiscoverPack`"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Using `download_llama_pack`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.llama_pack import download_llama_pack\n",
    "\n",
    "SelfDiscoverPack = download_llama_pack(\"SelfDiscoverPack\", \"./self_discover_pack\")\n",
    "\n",
    "self_discover_pack = SelfDiscoverPack(verbose=True, llm=llm)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Directly use `SelfDiscoverPack`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.packs.self_discover import SelfDiscoverPack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "self_discover_pack = SelfDiscoverPack(verbose=True, llm=llm)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test out on some tasks"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Task\n",
    "\n",
    "Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. Then, Michael goes to the market and buys 12 more oranges and 5 more apples. If Michael decides to give 2 apples to his friend, how many oranges and apples does Michael have now?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running step get_modules\n",
      "Step get_modules produced event GetModulesEvent\n",
      "Running step refine_modules\n",
      "Step refine_modules produced event RefineModulesEvent\n",
      "Running step create_reasoning_structure\n",
      "Step create_reasoning_structure produced event ReasoningStructureEvent\n",
      "Running step get_final_result\n",
      "Step get_final_result produced event StopEvent\n"
     ]
    }
   ],
   "source": [
    "task = \"Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. Then, Michael goes to the market and buys 12 more oranges and 5 more apples. If Michael decides to give 2 apples to his friend, how many oranges and apples does Michael have now?\"\n",
    "output = self_discover_pack.run(task)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Michael initially has 15 oranges and 0 apples.\n",
      "2. After giving 4 oranges to his brother, Michael has 15 - 4 = 11 oranges.\n",
      "3. After trading 3 oranges with his neighbor, Michael has 11 - 3 = 8 oranges.\n",
      "4. After receiving 6 apples from the trade, Michael has 0 + 6 = 6 apples.\n",
      "5. After discarding 2 spoiled oranges, Michael has 8 - 2 = 6 oranges.\n",
      "6. After buying 12 more oranges and 5 more apples at the market, Michael has 6 + 12 = 18 oranges and 6 + 5 = 11 apples.\n",
      "7. After giving 2 apples to his friend, Michael has 11 - 2 = 9 apples.\n",
      "8. The final number of oranges and apples Michael has is 18 oranges + 9 apples = 27 fruits.\n",
      "9. All transactions have been accounted for.\n",
      "10. Therefore, Michael has 18 oranges and 9 apples after all transactions.\n"
     ]
    }
   ],
   "source": [
    "print(output)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Task\n",
    "\n",
    "Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs $3 per jar and ground beef costs $5 per pound. Tom buys 2 jars of tomato sauce and 2 pounds of ground beef. He also picks up a loaf of bread for $2.50. If Tom pays with a $50 bill, how much change should he receive after purchasing these items?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running step get_modules\n",
      "Step get_modules produced event GetModulesEvent\n",
      "Running step refine_modules\n",
      "Step refine_modules produced event RefineModulesEvent\n",
      "Running step create_reasoning_structure\n",
      "Step create_reasoning_structure produced event ReasoningStructureEvent\n",
      "Running step get_final_result\n",
      "Step get_final_result produced event StopEvent\n"
     ]
    }
   ],
   "source": [
    "task = \"Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs $3 per jar and ground beef costs $5 per pound. Tom buys 2 jars of tomato sauce and 2 pounds of ground beef. He also picks up a loaf of bread for $2.50. If Tom pays with a $50 bill, how much change should he receive after purchasing these items?\"\n",
    "output = self_discover_pack.run(task)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. The cost of each item Tom needs to buy is: 2 jars of tomato sauce at $3 each, 2 pounds of ground beef at $5 each, and a loaf of bread for $2.50.\n",
      "2. The total cost of the tomato sauce is 2 jars * $3/jar = $6.\n",
      "3. The total cost of the ground beef is 2 pounds * $5/pound = $10.\n",
      "4. The total cost of the items is $6 (tomato sauce) + $10 (ground beef) + $2.50 (bread) = $18.50.\n",
      "5. If Tom pays with a $50 bill, the amount of change he should receive is $50 - $18.50 = $31.50.\n",
      "6. There are no hidden costs or discounts mentioned in the problem, so the total cost and the amount of change should not be affected.\n",
      "7. The calculations have been verified and all necessary data has been considered.\n",
      "8. Therefore, Tom should receive $31.50 in change after purchasing these items.\n"
     ]
    }
   ],
   "source": [
    "print(output)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "llama",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  },
  "vscode": {
   "interpreter": {
    "hash": "b1d2a638b53f4d7129cb7686d8e3b97ae1d80a593a1618479f60cef5591ea888"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
